import logging
import subprocess

import PIL
from _tkinter import TclError
from ttkbootstrap.constants import *
from tkinter.messagebox import *
import ttkbootstrap as ttk
import view
import ttkbootstrap.utility as utility
import traceback
import pdf
import os

intro = """
1.管理您库存的商品，归类，添加，更改，删除，搜索。

2.管理您的单子，同样单子也有商品一样的特性除外，还可以在您磁盘上导出，并持久保存。
"""
auth = """
开发:Ihsan
1843398977@qq.com
"""


# Good Manager call_back functions

def callback_func_of_add_groups(*args):
    if AddGroupsWindow.is_live is not None:
        AddGroupsWindow.is_live.destroy()
        del AddGroupsWindow.is_live
    AddGroupsWindow.is_live = AddGroupsWindow(title="添加货物组")


def callback_func_of_add_goods(*args):
    if AddGoodsWindow.is_live is not None:
        AddGoodsWindow.is_live.destroy()
        del AddGoodsWindow.is_live
    AddGoodsWindow.is_live = AddGoodsWindow(title="添加货物信息")


def callback_func_of_change_information_of_goods(item_info: tuple):
    if ChangeGoodsInformationWindow.is_live is not None:
        ChangeGoodsInformationWindow.is_live.destroy()
        del ChangeGoodsInformationWindow.is_live
    ChangeGoodsInformationWindow.is_live = ChangeGoodsInformationWindow(
        title="更改货物信息")
    group_name = item_info[1]
    good_name = item_info[2]
    good_price = item_info[3]
    good_image = item_info[4]
    ChangeGoodsInformationWindow.is_live.name.set(good_name)
    ChangeGoodsInformationWindow.is_live.group_name.set(group_name)
    ChangeGoodsInformationWindow.is_live.price.set(good_price)
    ChangeGoodsInformationWindow.is_live.good_image.set(good_image)
    ChangeGoodsInformationWindow.good_id = item_info[0]


def callback_func_of_change_information_of_groups(item_info: tuple):
    if ChangeGroupInformationWindow.is_live is not None:
        ChangeGroupInformationWindow.is_live.destroy()
        del ChangeGroupInformationWindow.is_live
        ChangeGroupInformationWindow.is_live = None
    ChangeGroupInformationWindow.is_live = ChangeGroupInformationWindow(
        title="更改组信息")
    group_name = item_info[1]
    group_image = item_info[2]
    ChangeGroupInformationWindow.is_live.name.set(group_name)
    ChangeGroupInformationWindow.is_live.group_image.set(group_image)
    ChangeGroupInformationWindow.group_id = item_info[0]


def callback_func_of_add_group_confirm(group_name, group_image):
    try:
        if len(group_name) > view.GROUP_NAME_MAX_LEN:
            showerror("错误", "组名太长了， 控制在30个汉词之内。")
            return False
        if group_name == "":
            showerror("错误", "组名不能为空。")
            return False
        if not view.select_group_by_name(group_name) is None:
            showerror("错误", "组名存在，请使用别的组名。")
            return False
        group_image = view.DEFAULT_GROUP_IMAGE if group_image == "" else group_image
        view.verify_image(group_image)
        return view.insert_into_group(group_name, group_image)
    except Exception as e:
        view.logger.error(traceback.print_exc())
        view.logger.error(e)


def callback_func_of_add_good_confirm(group_name, good_name, good_price, good_image):
    try:
        if good_name == "":
            showerror("错误", "名字不能为空。")
            return False
        if len(good_name) > view.GOOD_NAME_MAX_LEN:
            showerror("错误", "货物名字控制在30个字符之内。")
            return False
        goods_in_group = view.get_goods_name_id_from_group_name(
            group_name=group_name)
        for row in goods_in_group:
            if good_name in row:
                showerror("错误", "此组已存在相同名字的货物，请使用别的名字。")
                return False
        if view.get_group_from_name(group_name) is None:
            showerror("错误", "组不存在，请输入已存在的组。")
            return False
        if good_price == "":
            showerror("错误", "货物价格不能为空.")
            return False
        good_image = view.DEFAULT_GOOD_IMAGE if good_image == "" else good_image
        view.verify_image(good_image)
        return view.insert_into_good(group_name, good_name, good_price, good_image)
    except Exception as e:
        view.logger.error(traceback.print_exc())
        view.logger.error(e)
        return False


def callback_func_of_change_information_group_confirm(group_id, group_name, group_image):
    try:
        if len(group_name) > view.GROUP_NAME_MAX_LEN:
            showerror("错误", "组名太长了， 控制在30个汉词之内。")
            return False
        if group_name == "":
            showerror("错误", "组名不能为空。")
            return False
        group_info = view.select_group_by_name(group_name)
        if not (group_info is None and group_id not in group_info):
            showerror("错误", "组名存在，请使用别的组名或者使用原来的组名。")
            return False
        group_image = view.DEFAULT_GROUP_IMAGE if group_image == "" else group_image
        view.verify_image(group_image)
        return view.update_group_information(group_id, group_name, group_image)
    except Exception as e:
        view.logger.error(traceback.print_exc())
        view.logger.error(e)


def callback_func_of_change_information_good_confirm(good_id, group_name, good_name, good_price, good_image):
    try:
        if good_name == "":
            showerror("错误", "名字不能为空。")
            return False
        if len(good_name) > view.GOOD_NAME_MAX_LEN:
            showerror("错误", "货物名字控制在30个字符之内。")
            return False
        goods_in_group = view.get_goods_name_id_from_group_name(
            group_name=group_name)
        for row in goods_in_group:
            if good_name in row and good_id not in row:
                showerror("错误", "此组已存在相同名字的货物，请使用别的名字。")
                return False
        if view.get_group_from_name(group_name) is None:
            showerror("错误", "组不存在，请输入已存在的组。")
            return False
        if good_price == "":
            showerror("错误", "货物价格不能为空.")
            return False
        good_image = view.DEFAULT_GOOD_IMAGE if good_image == "" else good_image
        view.verify_image(good_image)
        return view.update_good_information(good_id, group_name, good_name, good_price, good_image)
    except Exception as e:
        view.logger.error(traceback.print_exc())
        view.logger.error(e)
        return False


# Index callback functions
def callback_func_of_index_goods():
    if view.GOODS_TREE_FRAME is not None:
        view.GOODS_TREE_FRAME.destroy()
        del view.GOODS_TREE_FRAME
        view.GOODS_TREE_FRAME = None
    view.GOODS_TREE_FRAME = ttk.Toplevel(
        master=view.ROOT_WINDOW,
        minsize=(530, 400),
    )
    view.GOODS_TREE = GoodManager(view.GOODS_TREE_FRAME)


def callback_func_of_index_setting():
    if view.SETTING is not None:
        view.SETTING.destroy()
        del view.SETTING
        view.SETTING = None
    view.SETTING = Setting()


def callback_func_of_index_order():
    if view.ORDER is not None:
        view.ORDER.destroy()
        del view.ORDER
        view.ORDER = None
    view.ORDER = Order()


# Order callback functions
def callback_func_of_order_double_click_good(good_information: tuple):
    if OrderSelectGood.is_live is not None:
        OrderSelectGood.is_live.destroy()
        del OrderSelectGood.is_live
        OrderSelectGood.is_live = None
    OrderSelectGood.is_live = OrderSelectGood(good_information)


def callback_func_of_add_order_confirm(good_information: tuple, number: int):
    try:
        good_id = good_information[0]
        goods_name = good_information[2]
        price = good_information[3]
        sum_price = number * price
        # 往 order tree 新增一个订单item
        view.ORDER.order_tree.insert(
            "", END, text=good_id, values=(goods_name, str(price) + "¥", number, str(sum_price) + "¥")
        )
        view.ORDER.is_save_order.set(False)
    except Exception as e:
        view.logger.error(traceback.print_exc())
        view.logger.error(e)
        showerror("错误", f"试图新增一个订单信息的时候出错。\n{e}")


def callback_func_of_modify_order(good_information: list, number: str):
    if ModifyOrderItem.is_live is not None:  # 如果存在修改信息窗口
        ModifyOrderItem.is_live.destroy()  # 毁掉以前存在的
        del ModifyOrderItem.is_live
        ModifyOrderItem.is_live = None
    ModifyOrderItem.is_live = ModifyOrderItem(good_information, number)


def callback_func_of_modify_order_confirm(good_information: list, number: int):
    try:
        goods_name = good_information[2]
        price = good_information[3]
        sum_price = number * price
        iid = good_information[5]
        # 往 order tree 新增一个订单item
        view.ORDER.order_tree.item(iid,
                                   values=(goods_name, str(good_information[3]) + "¥", number, str(sum_price) + "¥"))
        view.ORDER.is_save_order.set(False)
    except Exception as e:
        view.logger.error(traceback.print_exc())
        view.logger.error(e)
        showerror("错误", f"试图修改一个订单信息的时候出错。\n{e}")


def callback_func_of_save_order(goods: list):
    if SaveOrder.is_live is not None:  # 如果存在修改信息窗口
        SaveOrder.is_live.destroy()  # 毁掉以前存在的
        del SaveOrder.is_live
        SaveOrder.is_live = None
    SaveOrder.is_live = SaveOrder(goods)


def callback_func_of_save_order_confirm(remark: str, goods: list):
    try:
        # 数据库表中插入新的orders_group记录 -- 此记录是一个订单组，包含此次订购的货物
        order_group_id = view.insert_into_order_group(remark)
        if not order_group_id:
            return
        # 生成存放路径
        save_base_path = view.get_order_base_save_path()  # 获取订单存放文件夹
        if not save_base_path:
            return
        order_create_date = view.get_orders_group_create_date_by_orders_group_id(order_group_id)  # 获取创建时间
        if not order_create_date:
            return
        file_name = order_create_date.split(' ')[0] + "-" + str(order_group_id) + ".pdf"  # example ： 2022-9-12-3.pdf
        save_path = os.path.join(save_base_path, file_name)
        # orders表中插入，此次订购的所有货物。
        if not view.insert_into_orders(order_group_id, goods):
            return
        # 生成PDF
        if not pdf.generate_pdf(save_path, order_group_id):
            return
        # 更新orders_group中的save_path信息
        if not view.update_order_path_by_order_group_id(save_path, order_group_id):
            return
        # 更新最近保存的订单组ID
        view.ORDER.latest_order_group_id.set(order_group_id)
        # 更新保存功能状态
        view.ORDER.is_save_order.set(True)
        showinfo("成功", "成功保存订单.")
    except Exception as e:
        view.logger.error(traceback.print_exc())
        view.logger.error(e)
        showerror("错误", f"试图存储订单的时候出错。\n{e}")


def callback_func_of_order_history(*args):
    if OrderHistory.is_live is not None:  # 如果存在修改信息窗口
        OrderHistory.is_live.destroy()  # 毁掉以前存在的
        del OrderHistory.is_live
        OrderHistory.is_live = None
    OrderHistory.is_live = OrderHistory()


# common class
class MyException(BaseException):
    pass


class BaseToplevel(ttk.Toplevel):

    def __init__(self, **keyword):
        super().__init__(
            minsize=(400, 200),
            **keyword
        )
        self.images = {
            'folder': ttk.ImageTk.PhotoImage(image=ttk.Image.open(view.IMG_PATH / "folder.png").resize((15, 15)))
        }
        self.position_center()
        self.p_frame = ttk.Frame(self)
        self.p_frame.pack(
            fill=BOTH,
            expand=YES,
            padx=1,
            pady=1
        )
        self.path_button = ttk.Frame(self.p_frame)
        self.path_button.pack(
            side=BOTTOM,
            fill=X,
            expand=YES,
            pady=4,
            padx=4
        )
        ttk.Button(
            master=self.path_button,
            text="确定",
            command=self.confirm,
            width=8
        ).pack(side=LEFT, expand=YES, padx=1, pady=2)
        ttk.Button(
            master=self.path_button,
            text="取消",
            command=self.cancel,
            width=8
        ).pack(side=RIGHT, expand=YES, padx=1, pady=2)

    def cancel(self):
        self.destroy()

    def confirm(self):
        print("ok")
        pass


class OneEntryWindow(BaseToplevel):

    def __init__(self, label_name, **keyword):
        super().__init__(**keyword)
        self.path_row_1 = ttk.Frame(self.p_frame)
        self.path_row_1.pack(
            side=TOP,
            fill=X,
            expand=YES,
            padx=4,
            pady=4
        )
        self.name = ttk.StringVar()
        ttk.Label(
            master=self.path_row_1,
            text=label_name,
            width=10,
            anchor=CENTER
            # ).grid(row=0, column=0)
        ).pack(side=LEFT)
        ttk.Entry(
            master=self.path_row_1,
            textvariable=self.name
            # ).grid(row=0, column=1, sticky=EW)
        ).pack(side=LEFT, expand=True, fill=X)


# good manager class
class AddGoodsWindow(OneEntryWindow):
    is_live = None  # 实例对象存在的话，会被赋给此变量，且此类的实例只会存在一个

    def __init__(self, **keyword):
        super().__init__("货物名字", **keyword)
        self.image_path = ttk.StringVar()
        self.path_row_2 = ttk.Frame(self.p_frame)
        self.path_row_2.pack(
            side=TOP,
            fill=X,
            expand=YES,
            padx=4,
            pady=4
        )
        self.group_name = ttk.StringVar()
        ttk.Label(
            master=self.path_row_2,
            text="货物组名字",
            width=10,
            anchor=CENTER
        ).pack(side=LEFT)
        ttk.Entry(
            master=self.path_row_2,
            textvariable=self.group_name
        ).pack(side=LEFT, fill=X, expand=YES)
        self.path_row_3 = ttk.Frame(self.p_frame)
        self.path_row_3.pack(
            side=TOP,
            fill=X,
            expand=YES,
            padx=4,
            pady=4
        )
        self.price = ttk.StringVar()
        ttk.Label(
            master=self.path_row_3,
            text="价格",
            width=10,
            anchor=CENTER
        ).pack(side=LEFT)
        ttk.Entry(
            master=self.path_row_3,
            textvariable=self.price
        ).pack(side=LEFT, fill=X, expand=YES)
        self.path_row_4 = ttk.Frame(self.p_frame)
        self.path_row_4.pack(
            side=TOP,
            fill=X,
            expand=YES,
            padx=4,
            pady=4
        )
        ttk.Label(
            master=self.path_row_4,
            text="图片",
            width=10,
            anchor=CENTER
            # ).grid(row=1, column=0)
        ).pack(side=LEFT)
        self.frame_openfolder = ttk.Frame(
            master=self.path_row_4,
            # ).grid(row=1, column=1, sticky=EW)
        )
        self.good_image = ttk.StringVar()
        self.frame_openfolder.pack(side=LEFT, expand=True, fill=X)
        ttk.Entry(
            master=self.frame_openfolder,
            textvariable=self.good_image
        ).pack(side=LEFT, expand=True, fill=X)
        ttk.Button(
            master=self.frame_openfolder,
            image=self.images['folder'],
            text="浏览",
            compound=LEFT,
            bootstyle="primary,success-outline",
            command=lambda: view.select_folder(self.good_image)
        ).pack(side=RIGHT, expand=False)
        self.set_group_name()

    def confirm(self):
        if callback_func_of_add_good_confirm(
                group_name=self.group_name.get(),
                good_name=self.name.get(),
                good_price=self.price.get(),
                good_image=self.good_image.get()
        ):
            showinfo("成功", "添加货物成功!")
            GoodManager.show_goods(view.GOODS_TREE)
            self.destroy()

    def set_group_name(self):
        group_name = ""
        if not view.GOODS_TREE.goods_tree.selection():
            group_name = self.group_name.get()
        else:
            is_group, item = view.GOODS_TREE.decide_select_item_is_group(
                view.GOODS_TREE)
            if is_group:
                group_name = view.GOODS_TREE.goods_tree.item(item, "text")
            else:
                parant = view.GOODS_TREE.goods_tree.parent(item)
                group_name = view.GOODS_TREE.goods_tree.item(parant, "text")
        self.group_name.set(group_name)


class AddGroupsWindow(OneEntryWindow):
    is_live = None  # 实例对象存在的话，会被赋给此变量，且此类的实例只会存在一个

    def __init__(self, **keyword):
        super().__init__("组名", **keyword)
        self.path_row_2 = ttk.Frame(self.p_frame)
        self.path_row_2.pack(
            side=TOP,
            fill=X,
            expand=YES,
            padx=4,
            pady=4
        )
        ttk.Label(
            master=self.path_row_2,
            text="图片",
            width=10,
            anchor=CENTER
            # ).grid(row=1, column=0)
        ).pack(side=LEFT)
        self.frame_openfolder = ttk.Frame(
            master=self.path_row_2,
            # ).grid(row=1, column=1, sticky=EW)
        )
        self.group_image = ttk.StringVar()
        self.frame_openfolder.pack(side=LEFT, expand=True, fill=X)
        self.folder_entry = ttk.Entry(
            master=self.frame_openfolder,
            textvariable=self.group_image
        )
        self.folder_entry.pack(side=LEFT, expand=True, fill=X)
        ttk.Button(
            master=self.frame_openfolder,
            image=self.images['folder'],
            text="浏览",
            compound=LEFT,
            bootstyle="primary,success-outline",
            command=lambda: view.select_folder(self.group_image)
        ).pack(side=RIGHT, expand=False)

    def confirm(self):
        if callback_func_of_add_group_confirm(
                self.name.get(),
                self.group_image.get()):
            showinfo("成功", "添加组成功!")
            GoodManager.show_goods(view.GOODS_TREE)
            self.destroy()


class ChangeGoodsInformationWindow(AddGoodsWindow):
    is_live = None
    good_id = None

    def __init__(self, **kwargs):
        super().__init__(**kwargs)

    def confirm(self):
        if callback_func_of_change_information_good_confirm(
                good_id=self.good_id,
                group_name=self.group_name.get(),
                good_name=self.name.get(),
                good_price=self.price.get(),
                good_image=self.good_image.get()
        ):
            showinfo("成功", "更改货物信息成功!")
            GoodManager.show_goods(view.GOODS_TREE)
            self.destroy()


class ChangeGroupInformationWindow(AddGroupsWindow):
    is_live = None
    group_id = None

    def __init__(self, **kwargs):
        super().__init__(**kwargs)

    def confirm(self):
        if callback_func_of_change_information_group_confirm(
                group_id=self.group_id,
                group_name=self.name.get(),
                group_image=self.group_image.get()):
            showinfo("成功", "更改组信息成功!")
            GoodManager.show_goods(view.GOODS_TREE)
            self.destroy()


# order manager class
class OrderSelectGood(BaseToplevel):
    is_live = None

    def __init__(self, good_information: tuple):
        super().__init__(title="新增一个订单信息")
        self.good_information = good_information
        self.path_row_1 = ttk.Frame(self.p_frame)
        self.path_row_1.pack(
            side=TOP,
            fill=X,
            expand=YES,
            padx=4,
            pady=4
        )
        self.number = ttk.StringVar(value="1")
        ttk.Label(
            master=self.path_row_1,
            text="数量 :",
            width=10,
            anchor=CENTER,
            font=("", 16, "normal")
        ).pack(side=LEFT)
        ttk.Entry(
            master=self.path_row_1,
            textvariable=self.number,
            width=25
        ).pack(side=LEFT)
        self.path_row_2 = ttk.Frame(self.p_frame)
        self.path_row_2.pack(
            side=TOP,
            fill=X,
            expand=YES,
            padx=4,
            pady=4
        )
        ttk.Label(
            master=self.path_row_2,
            text=f"物品: {self.good_information[2]},  价格: {self.good_information[3]}",
            anchor=CENTER,
            font=("", 18, "bold")
        ).pack(side=TOP)

    def confirm(self):
        tmp = self.number.get()
        if tmp is None or not tmp.isdecimal() or int(tmp) == 0:
            showerror("错误", "请输入有效整数")
            return
        callback_func_of_add_order_confirm(self.good_information, int(tmp))
        self.destroy()


class ModifyOrderItem(BaseToplevel):
    is_live = None

    def __init__(self, good_information: list, number: str):
        super().__init__(title="修改订单信息")
        self.good_information = good_information
        self.path_row_1 = ttk.Frame(self.p_frame)
        self.path_row_1.pack(
            side=TOP,
            fill=X,
            expand=YES,
            padx=4,
            pady=4
        )
        self.number = ttk.StringVar()
        self.number.set(number)
        ttk.Label(
            master=self.path_row_1,
            text="数量 :",
            width=10,
            anchor=CENTER,
            font=("", 16, "normal")
        ).pack(side=LEFT)
        ttk.Entry(
            master=self.path_row_1,
            textvariable=self.number,
            width=25
        ).pack(side=LEFT)
        self.path_row_2 = ttk.Frame(self.p_frame)
        self.path_row_2.pack(
            side=TOP,
            fill=X,
            expand=YES,
            padx=4,
            pady=4
        )
        ttk.Label(
            master=self.path_row_2,
            text=f"物品: {self.good_information[2]},  价格: {self.good_information[3]}",
            anchor=CENTER,
            font=("", 18, "bold")
        ).pack(side=TOP)

    def confirm(self):
        tmp = self.number.get()
        if tmp is None or not tmp.isdecimal() or int(tmp) == 0:
            showerror("错误", "请输入有效整数")
            return
        callback_func_of_modify_order_confirm(self.good_information, int(tmp))
        self.destroy()


class AutoScrollbar(ttk.Scrollbar):

    # Defining set method with all
    # its parameter
    def set(self, low, high):

        if float(low) <= 0.0 and float(high) >= 1.0:

            # Using grid_remove
            self.tk.call("grid", "remove", self)
        else:
            self.grid()
        ttk.Scrollbar.set(self, low, high)

    # Defining pack method
    def pack(self, **kw):

        # If pack is used it throws an error
        raise (TclError, "pack cannot be used with this widget")

    # Defining place method
    def place(self, **kw):

        # If place is used it throws an error
        raise (TclError, "place cannot be used with this widget")


class SaveOrder(BaseToplevel):
    is_live = None

    def __init__(self, goods: list):
        super().__init__(title="存储订单")
        self.goods = goods
        self.path_row_1 = ttk.Frame(self.p_frame)
        self.path_row_1.pack(
            side=TOP,
            fill=X,
            expand=YES,
            padx=4,
            pady=4
        )
        self.remark = ttk.StringVar()
        self.remark.set('无')
        ttk.Label(
            master=self.path_row_1,
            text="备注 :",
            width=10,
            anchor=CENTER,
            font=("", 16, "normal")
        ).pack(side=LEFT)
        ttk.Entry(
            master=self.path_row_1,
            textvariable=self.remark,
            width=25
        ).pack(side=LEFT)
        self.path_row_2 = ttk.Frame(self.p_frame)
        self.path_row_2.pack(
            side=TOP,
            fill=X,
            expand=YES,
            padx=4,
            pady=4
        )

    def confirm(self):
        callback_func_of_save_order_confirm(self.remark.get(), self.goods)
        self.destroy()


# Windows start
class GoodManager(ttk.Frame):
    is_live = None

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.pack(fill=BOTH, expand=True)

        # self.styles = [
        #     ttk.Style().configure("joe.Treeview", rowheight=40, font=("JetBrains Mono", 15, "normal")),
        # ]
        self.new_styles = [
            ttk.Style().configure("joe.Treeview", rowheight=view.TREEVIEW_ROW_HEIGHT,
                                  font=("JetBrains Mono", 15, "normal")),
        ]
        self.image_folder = []
        # region    功能函数区域
        # Function container
        frame_of_function = ttk.Frame(
            master=self,
            relief=RAISED,
            padding=5,
            # width=130,
            borderwidth=2,
            # style=LIGHT,
        )
        frame_of_function.pack(
            side=LEFT,
            fill=Y
        )
        frame_of_function.columnconfigure(0, weight=1)
        frame_of_function.rowconfigure(0, weight=1)
        frame_of_function.columnconfigure(1, weight=1)
        frame_of_function.rowconfigure(1, weight=1)
        frame_of_function.columnconfigure(2, weight=1)
        frame_of_function.rowconfigure(2, weight=1)

        self.fonts = [
            ttk.font.Font(size=12, weight="bold")
        ]
        # button of Add group
        add_group = ttk.Label(
            master=frame_of_function,
            relief=RAISED,
            borderwidth=10,
            text="添加货物组",
            background="DodgerBlue",
            padding=3,
            font=self.fonts[0],
            anchor=CENTER,
            foreground="white"
        )
        add_group.grid(row=0, column=0, sticky=NSEW)
        add_group.bind("<Button-1>", callback_func_of_add_groups)

        # button of Add goods
        add_good = ttk.Label(
            master=frame_of_function,
            relief=RAISED,
            borderwidth=10,
            text="添加货物",
            background="DodgerBlue",
            padding=3,
            font=self.fonts[0],
            anchor=CENTER,
            foreground="white"
        )
        add_good.grid(row=1, column=0, sticky=NSEW)
        add_good.bind("<Button-1>", callback_func_of_add_goods)

        # button of Delete
        delete_group = ttk.Label(
            master=frame_of_function,
            relief=RAISED,
            borderwidth=10,
            text="移除",
            background="LightGrey",
            padding=3,
            font=self.fonts[0],
            anchor=CENTER
        )
        delete_group.grid(row=2, column=0, sticky=NSEW)
        delete_group.bind("<Button-1>", self.delete_item)
        # endregion
        # region    展示货物区域
        # Goods container
        self.frame_of_goods = ttk.Frame(
            master=self,
            relief=RAISED,
            padding=5,
            width=600,
            borderwidth=2,
            # bootstyle=LIGHT
        )
        self.frame_of_goods.pack(
            side=LEFT,
            expand=True,
            fill=BOTH
        )
        self.frame_of_goods.grid_rowconfigure(index=0, weight=1)
        self.frame_of_goods.grid_columnconfigure(index=0, weight=1)

        column = ('组名', '货物ID', '货物名字', '货物价钱')
        self.goods_tree = ttk.Treeview(
            master=self.frame_of_goods,
            columns=column[1:],
            show=TREEHEADINGS,
            displaycolumns="#all",
            bootstyle="default",
            height=5,
            selectmode=BROWSE
        )
        self.xscroll = AutoScrollbar(
            master=self.frame_of_goods,
            orient=HORIZONTAL,
            bootstyle="primary-round",
            command=self.goods_tree.xview
        )
        self.yscroll = AutoScrollbar(
            master=self.frame_of_goods,
            orient=VERTICAL,
            bootstyle="primary-round",
            command=self.goods_tree.yview
        )
        self.goods_tree.configure(
            xscrollcommand=self.xscroll.set, yscrollcommand=self.yscroll.set)

        self.xscroll.grid(row=1, column=0, sticky=EW)
        self.yscroll.grid(row=0, column=1, sticky=NS)
        self.goods_tree.grid(row=0, column=0, sticky=NSEW)

        self.goods_tree.bind("<Double-Button-1>",
                             self.double_click_the_treeview_item)
        self.goods_tree.heading("#0", text=column[0], anchor=W)
        self.goods_tree.heading(column[1], text=column[1], anchor=W)
        self.goods_tree.heading(column[2], text=column[2], anchor=W)
        self.goods_tree.heading(column[3], text=column[3], anchor=W)
        self.goods_tree.column(column="#0", anchor=W)
        self.goods_tree.column(column=column[1], anchor=W)
        self.goods_tree.column(column=column[2], anchor=W)
        self.goods_tree.column(column=column[3], anchor=W)
        self.show_goods()
        # self.goods_tree.heading("#0", text='组', anchor=CENTER)
        # self.goods_tree.heading(0, text='货物编号', anchor=CENTER)
        # self.goods_tree.heading(1, text='货物名字', anchor=CENTER)
        # self.goods_tree.heading(2, text='货物价格', anchor=CENTER)
        # # self.goods_tree.heading(2, text='image', anchor=CENTER)
        # self.goods_tree.column(
        #     column="#0",
        #     width=utility.scale_size(self, 200),
        #     anchor=CENTER
        # )
        # self.goods_tree.column(
        #     column=0,
        #     width=utility.scale_size(self, 50),
        #     anchor=CENTER
        # )
        # self.goods_tree.column(
        #     column=1,
        #     width=utility.scale_size(self, 300),
        #     anchor=CENTER
        # )
        # self.goods_tree.column(
        #     column=2,
        #     width=utility.scale_size(self, 300),
        #     anchor=CENTER
        # )
        # endregion

    def delete_item(self, *args):
        """
        1、判断所选item是组还是组元素 --> 这里判断的原因是，防止误操作，把组给删掉。
        2、删除相应的记录，重新渲染 --> show_goods()
        :param args:
        :return:
        """
        try:
            is_group, item = self.decide_select_item_is_group()
            if is_group:
                group_name = self.goods_tree.item(item, "text")
                if askyesno("Delete", "确定删除此组吗？删除会导致组下面的所有货物都会被删掉"):
                    self.delete_group(group_name)
            else:
                good_id = self.goods_tree.item(item, "values")[0]
                if askyesno("Delete", "确定删除此货物吗？"):
                    self.delete_good(good_id)
        except Exception as e:
            view.logger.error(traceback.print_exc())
            view.logger.error(e)

    def delete_good(self, good_id):
        if view.delete_good_by_id(good_id):
            self.show_goods()

    def delete_group(self, group_name):
        if view.delete_group_by_name(group_name):
            self.show_goods()

    def show_goods(self, *args):
        try:
            self.clean_tree()
            item = 0
            all_groups = view.get_all_groups()
            if all_groups is False:
                return
            for group_id, group_name, group_image in all_groups:
                self.image_folder.append(ttk.ImageTk.PhotoImage(
                    image=view.set_image_size(
                        image_path=group_image,
                        size=view.GROUP_IMAGE_SIZE)
                ))
                father = self.goods_tree.insert(
                    parent="",
                    index=END,
                    text=group_name,
                    image=self.image_folder[item]
                )
                self.goods_tree.item(father, tags="group")
                item = item + 1
                goods = view.get_goods_from_group_name(group_name)
                if goods is False:
                    continue
                for good in goods:
                    self.image_folder.append(ttk.ImageTk.PhotoImage(
                        image=view.set_image_size(
                            image_path=good[4],
                            size=view.GOOD_IMAGE_SIZE
                        )
                    ))
                    self.goods_tree.insert(
                        parent=father,
                        index=END,
                        values=[good[0], good[2], good[3]],
                        image=self.image_folder[item]
                    )
                    item = item + 1
            # 设置货物组字体比货物字体醒目
            self.goods_tree.tag_configure("group", font=(
                view.TREEVIEW_GROUP_FONT_FAMILY, view.TREEVIEW_GROUP_FONT_SIZE, view.TREEVIEW_GROUP_FONT_STYLE))
        except Exception as e:
            view.logger.error(traceback.print_exc())
            view.logger.error(e)

    def double_click_the_treeview_item(self, *args):
        try:
            is_group, item = self.decide_select_item_is_group()
            if is_group:
                group_name = self.goods_tree.item(item, "text")
                group_info_from_db = view.get_group_from_name(
                    group_name)
                if not group_info_from_db:
                    return
                callback_func_of_change_information_of_groups(
                    item_info=group_info_from_db)
            good_info_from_window = self.goods_tree.item(item, "values")
            good_info_from_db = view.get_goods_from_id(good_info_from_window[0])
            if not good_info_from_db:
                return
            callback_func_of_change_information_of_goods(item_info=good_info_from_db)
        except Exception as e:
            view.logger.error(traceback.print_exc())
            view.logger.error(e)

    def decide_select_item_is_group(self, *args):
        groups = self.goods_tree.get_children()
        select_item = self.goods_tree.selection()
        if not select_item:
            showwarning("错误️", "请选择一个元素")
            raise MyException("没选择元素")
        select_item = select_item[0]
        if select_item in groups:
            return True, select_item
        else:
            return False, select_item

    def clean_tree(self):
        self.image_folder.clear()
        x = self.goods_tree.get_children()
        for item in x:
            self.goods_tree.delete(item)


class Index(ttk.Frame):
    is_live = None

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.pack(fill=BOTH, expand=True)

        self.my_style = ttk.Style()
        self.my_style.configure("fonts.TButton", font=("", 20, "normal"))

        self.cfg = {
            "args_button": {
                "style": 'fonts.TButton',
                "pad": (70, 0, 70, 0),
            },
        }

        # left panel
        self.left_panel = ttk.Frame(
            master=self,
            width=20,
            # style="button_fonts"
        )
        self.left_panel.pack(side=LEFT, fill=Y)

        self.left_panel.grid_columnconfigure(0, minsize=20)
        self.left_panel.grid_rowconfigure(0, minsize=10)

        ttk.Label(
            master=self.left_panel,
            text="管理您的商品:)",
            foreground="gray",
            font=("", 12, "normal")
        ).grid(row=1, column=1, sticky="w")
        button_goods = ttk.Button(
            master=self.left_panel,
            text="商品",
            command=callback_func_of_index_goods,
            **self.cfg["args_button"],
        )
        button_goods.grid(
            row=2,
            column=1,
            columnspan=3,
            sticky=EW
        )

        self.left_panel.grid_rowconfigure(3, minsize=15)

        ttk.Label(
            master=self.left_panel,
            text="管理您的单子:)",
            foreground="gray",
            font=("", 12, "normal")
        ).grid(row=4, column=1, sticky="w")
        button_order = ttk.Button(
            master=self.left_panel,
            text="订单",
            command=callback_func_of_index_order,
            **self.cfg["args_button"],
        )
        button_order.grid(
            row=5,
            column=1,
            columnspan=3,
            sticky=EW
        )

        self.left_panel.grid_rowconfigure(6, minsize=15)

        ttk.Label(
            master=self.left_panel,
            text="配置属于您的系统:)",
            foreground="gray",
            font=("", 12, "normal")
        ).grid(row=7, column=1, sticky="w")
        # button body
        self.button_setting = ttk.Button(
            master=self.left_panel,
            text="设置",
            command=callback_func_of_index_setting,
            **self.cfg["args_button"],
        )
        self.button_setting.grid(
            row=8,
            column=1,
            columnspan=3,
            sticky=EW
        )

        self.left_panel.grid_rowconfigure(9, minsize=15)

        # intro
        intro_frame = ttk.Frame(
            master=self.left_panel,
            # borderwidth=1,
            # relief=RAISED,
        )
        intro_frame.grid(row=10, column=1)
        intro_label = ttk.Label(
            master=intro_frame,
            foreground="gray",
            text=intro,
            font=("", 12, "normal"),
            wraplength=180,
            anchor="nw",
        )
        intro_label.grid(row=0, column=0)

        # 作者信息
        intro_label = ttk.Label(
            master=intro_frame,
            foreground="gray",
            text=auth,
            font=("", 12, "normal"),
            wraplength=180,
            anchor="nw",
        )
        intro_label.grid(row=1, column=0)

        # welcome area
        self.welcome_image = self.get_welcome_image()
        ttk.Label(
            master=self,
            image=self.welcome_image,
            padding=10
        ).pack()

    @staticmethod
    def get_welcome_image():
        image_path = view.get_welcome_image()
        if not image_path:
            return
        image = ttk.ImageTk.PhotoImage(view.set_image_size(image_path, 600))
        return image


class Setting(BaseToplevel):
    def __init__(self, **kwargs):
        super().__init__(title="设置", **kwargs)
        self.images = {
            'folder': ttk.ImageTk.PhotoImage(image=ttk.Image.open(view.IMG_PATH / "folder.png").resize((15, 15)))
        }
        # 设置项
        self.welcome_image = ttk.StringVar(value=view.get_welcome_image())
        self.order_save_path = ttk.StringVar(value=view.get_order_base_save_path())
        self.app_path = ttk.StringVar(value=view.get_app_path())
        # 当值发生变化时，会设置对应的值为True
        self.trace_welcome_image_V = ttk.BooleanVar(value=False)
        self.trace_order_save_path_V = ttk.BooleanVar(value=False)
        self.trace_app_path_V = ttk.BooleanVar(value=False)
        # 跟踪
        self.welcome_image.trace("w", lambda *args: self.trace_welcome_image_V.set(True))
        self.order_save_path.trace("w", lambda *args: self.trace_order_save_path_V.set(True))
        self.app_path.trace("w", lambda *args: self.trace_app_path_V.set(True))

        self.p_body = ttk.Frame(
            master=self.p_frame
        )
        self.p_body.pack(
            side=TOP,
            fill=X,
            expand=True,
            pady=4,
            padx=4
        )
        self.p_body.grid_rowconfigure(0, weight=1)
        self.p_body.grid_rowconfigure(1, weight=1)
        self.p_body.grid_rowconfigure(2, weight=1)
        self.p_body.grid_columnconfigure(0, weight=1)
        # 设置照片墙
        self.one_row = ttk.Frame(
            master=self.p_body,
            padding=3,
        )
        self.one_row.grid(
            row=0,
            column=0,
            sticky=EW
        )
        ttk.Label(
            master=self.one_row,
            text="照片墙",
            width=10,
            anchor=CENTER
        ).pack(side=LEFT)
        self.frame_openfolder = ttk.Frame(
            master=self.one_row
        )
        self.frame_openfolder.pack(side=LEFT, expand=True, fill=X)
        self.folder_entry = ttk.Entry(
            master=self.frame_openfolder,
            textvariable=self.welcome_image
        )
        self.folder_entry.pack(side=LEFT, expand=True, fill=X)
        ttk.Button(
            master=self.frame_openfolder,
            image=self.images['folder'],
            text="浏览",
            compound=LEFT,
            bootstyle="primary",
            command=lambda: view.select_file(self.welcome_image)
        ).pack(side=RIGHT, expand=False)

        # 单子保存位置
        self.two_row = ttk.Frame(
            master=self.p_body,
            padding=3
        )
        self.two_row.grid(
            row=1,
            column=0,
            sticky=EW
        )
        ttk.Label(
            master=self.two_row,
            text="单子保存位置",
            width=10,
            anchor=CENTER
        ).pack(side=LEFT)
        self.frame_openfolder = ttk.Frame(
            master=self.two_row
        )
        self.frame_openfolder.pack(side=LEFT, expand=True, fill=X)
        self.folder_entry = ttk.Entry(
            master=self.frame_openfolder,
            textvariable=self.order_save_path
        )
        self.folder_entry.pack(side=LEFT, expand=True, fill=X)
        ttk.Button(
            master=self.frame_openfolder,
            image=self.images['folder'],
            text="浏览",
            compound=LEFT,
            bootstyle="primary",
            command=lambda: view.select_folder(self.order_save_path)
        ).pack(side=RIGHT, expand=False)

        # 浏览器路径设置
        self.three_row = ttk.Frame(
            master=self.p_body,
            padding=3
        )
        self.three_row.grid(
            row=2,
            column=0,
            sticky=EW
        )
        ttk.Label(
            master=self.three_row,
            text="浏览器路径",
            width=10,
            anchor=CENTER
        ).pack(side=LEFT)
        self.frame_openfolder = ttk.Frame(
            master=self.three_row
        )
        self.frame_openfolder.pack(side=LEFT, expand=True, fill=X)
        self.folder_entry = ttk.Entry(
            master=self.frame_openfolder,
            textvariable=self.app_path
        )
        self.folder_entry.pack(side=LEFT, expand=True, fill=X)
        ttk.Button(
            master=self.frame_openfolder,
            image=self.images['folder'],
            text="浏览",
            compound=LEFT,
            bootstyle="primary",
            command=lambda: view.select_folder(self.app_path)
        ).pack(side=RIGHT, expand=False)

    def set_welcome_image(self, *args):
        try:
            if view.update_config("welcome_image", self.welcome_image.get()):
                view.SETTING.destroy()
                showinfo("成功", "成功更改照片墙！")
                view.INDEX.destroy()
                view.INDEX = Index(view.ROOT_WINDOW)
        except Exception as e:
            view.logger.error(traceback.print_exc())
            view.logger.error(e)

    def set_order_save_path(self, *args):
        try:
            if view.update_config("orders_save_path", self.order_save_path.get()):
                showinfo("成功", "成功更改订单存放路径！")
        except Exception as e:
            view.logger.error(traceback.print_exc())
            view.logger.error(e)

    def set_app_path(self, *args):
        try:
            if view.update_config("app_path", self.app_path.get()):
                showinfo("成功", "成功更改浏览器路径！")
        except Exception as e:
            view.logger.error(traceback.print_exc())
            view.logger.error(e)

    def confirm(self):
        try:
            if self.trace_welcome_image_V.get():
                self.set_welcome_image()
            if self.trace_order_save_path_V.get():
                self.set_order_save_path()
            if self.trace_app_path_V.get():
                self.set_app_path()
            self.destroy()
        except Exception as e:
            view.logger.error(traceback.print_exc())
            view.logger.error(e)


class Order(ttk.Toplevel):

    def __init__(self, *args, **kwargs):
        super().__init__(minsize=(920, 590), title="订单管理", **kwargs)
        # 当保存过后，会把值设为True， 当订单树发生改变时会再次设置为False
        # 当值为True的时候不能点击保存按钮
        self.is_save_order = ttk.BooleanVar(master=self, value=False)
        self.is_save_order.trace('w', self.track_the_is_save_order)
        self.latest_order_group_id = ttk.IntVar(master=self, value=None)  # 存放最近保存的订单组ID

        self.image_folder = []
        self.image_buttons = {
            "clean": ttk.ImageTk.PhotoImage(view.set_image_size(view.IMG_PATH / "clean.png", view.BUTTON_IMAGE_SIZE)),
            "history": ttk.ImageTk.PhotoImage(
                view.set_image_size(view.IMG_PATH / "history.png", view.BUTTON_IMAGE_SIZE)),
            "print": ttk.ImageTk.PhotoImage(view.set_image_size(view.IMG_PATH / "print.png", view.BUTTON_IMAGE_SIZE)),
            "save": ttk.ImageTk.PhotoImage(view.set_image_size(view.IMG_PATH / "save.png", view.BUTTON_IMAGE_SIZE)),
            "modify": ttk.ImageTk.PhotoImage(view.set_image_size(view.IMG_PATH / "modify.png", view.BUTTON_IMAGE_SIZE)),
            "add": ttk.ImageTk.PhotoImage(view.set_image_size(view.IMG_PATH / "add.png", view.BUTTON_IMAGE_SIZE)),
        }

        # 统一设置侧边栏宽度
        self.grid_columnconfigure(0, weight=30)

        # region 上层
        self.top_frame = ttk.Frame(
            master=self,
        )
        self.top_frame.pack(
            side=TOP,
            expand=True,
            fill=BOTH
        )

        # region 上层-侧边栏
        self.top_left_panel = ttk.Frame(
            master=self.top_frame,
            padding=10,
        )
        self.top_left_panel.pack(
            side=LEFT,
            expand=False,
            fill=Y
        )
        self.top_left_panel.grid_columnconfigure(0, minsize=5)
        self.top_left_panel.columnconfigure(0, weight=1)

        # right_panel.grid_columnconfigure(4, minsize=5)

        ttk.Label(
            master=self.top_left_panel,
            text="商品选择",
            # image=self.image_buttons["order_logo"],
            # compound=BOTTOM,
            font=("", 21, "bold"),
        ).grid(
            row=0,
            column=1,
            sticky=EW
        )

        self.top_left_panel.grid_rowconfigure(1, minsize=30)
        ttk.Button(
            master=self.top_left_panel,
            text="添加",
            compound=LEFT,
            image=self.image_buttons["add"],
            command=self.double_click_the_treeview_item_good,
            bootstyle="info-outline",
        ).grid(
            row=2,
            column=1,
            sticky=EW
        )
        # endregion

        # region 上层-商品树
        # Goods container

        self.goods_frame = ttk.Frame(
            master=self.top_frame,
            padding=2,
        )
        self.goods_frame.pack(
            side=RIGHT,
            expand=True,
            fill=BOTH
        )
        self.goods_frame.grid_rowconfigure(index=0, weight=1)
        self.goods_frame.grid_columnconfigure(index=0, weight=1)

        column = ('组名', '货物ID', '货物名字', '货物价钱')
        self.goods_tree = ttk.Treeview(
            master=self.goods_frame,
            columns=column[1:],
            show=TREEHEADINGS,
            displaycolumns="#all",
            bootstyle="primary",
            height=5,
            selectmode=BROWSE
        )
        self.xscroll = AutoScrollbar(
            master=self.goods_frame,
            orient=HORIZONTAL,
            bootstyle="primary-round",
            command=self.goods_tree.xview
        )
        self.yscroll = AutoScrollbar(
            master=self.goods_frame,
            orient=VERTICAL,
            bootstyle="primary-round",
            command=self.goods_tree.yview
        )
        self.goods_tree.config(
            xscrollcommand=self.xscroll.set, yscrollcommand=self.yscroll.set)

        self.xscroll.grid(row=1, column=0, sticky=EW)
        self.yscroll.grid(row=0, column=1, sticky=NS)
        self.goods_tree.grid(row=0, column=0, sticky=NSEW)

        self.goods_tree.bind("<Double-Button-1>",
                             self.double_click_the_treeview_item_good)
        self.goods_tree.heading("#0", text=column[0], anchor=W)
        self.goods_tree.heading(column[1], text=column[1], anchor=W)
        self.goods_tree.heading(column[2], text=column[2], anchor=W)
        self.goods_tree.heading(column[3], text=column[3], anchor=W)
        self.goods_tree.column(column="#0", anchor=W)
        self.goods_tree.column(column=column[1], anchor=W)
        self.goods_tree.column(column=column[2], anchor=W)
        self.goods_tree.column(column=column[3], anchor=W)
        self.show_goods()
        # endregion

        # endregion

        # region separator - 分割线
        self.separator = ttk.Separator(
            master=self,
            orient=HORIZONTAL,
            takefocus=1
        )
        self.separator.pack(
            side=TOP,
            pady=5,
            fill=X
        )
        # endregion

        # region 下层
        self.bottom_frame = ttk.Frame(
            master=self,
        )
        self.bottom_frame.pack(
            side=BOTTOM,
            expand=True,
            fill=BOTH
        )

        # region 下层-侧边栏
        self.bottom_left_panel = ttk.Frame(
            master=self.bottom_frame,
            padding=10,
        )
        self.bottom_left_panel.pack(
            side=LEFT,
            expand=False,
            fill=Y
        )
        self.bottom_left_panel.grid_columnconfigure(0, minsize=5)
        ttk.Label(
            master=self.bottom_left_panel,
            text="订购商品",
            # image=self.image_buttons["record"],
            compound=BOTTOM,
            font=("", 21, "bold")
        ).grid(
            row=0,
            column=1,
            sticky=EW
        )
        self.bottom_left_panel.grid_rowconfigure(1, minsize=30)
        ttk.Button(
            master=self.bottom_left_panel,
            text="打印",
            compound=LEFT,
            image=self.image_buttons["print"],
            command=self.print_order_tree,
            bootstyle="info-outline",
        ).grid(
            row=2,
            column=1,
            sticky=EW
        )
        self.bottom_left_panel.grid_rowconfigure(3, minsize=20)
        ttk.Button(
            master=self.bottom_left_panel,
            text="修改",
            compound=LEFT,
            image=self.image_buttons["modify"],
            command=self.modify_order_from_order_tree,
            bootstyle="warning-outline",
        ).grid(
            row=4,
            column=1,
            sticky=EW
        )
        self.bottom_left_panel.grid_rowconfigure(5, minsize=20)
        self.save_order_btn = ttk.Button(
            master=self.bottom_left_panel,
            text="保存",
            compound=LEFT,
            image=self.image_buttons["save"],
            command=self.save_order_tree,
            bootstyle="success-outline",
        )
        self.save_order_btn.grid(
            row=6,
            column=1,
            sticky=EW
        )

        self.bottom_left_panel.rowconfigure(8, weight=1)
        self.bottom_left_down_button_frame = ttk.Frame(
            master=self.bottom_left_panel
        )
        self.bottom_left_down_button_frame.grid(
            row=8,
            column=1,
            sticky=W + E + S
        )
        self.history = ttk.Label(
            master=self.bottom_left_down_button_frame,
            image=self.image_buttons["history"],
        )
        self.history.pack(side=LEFT)
        self.history.bind("<Button-1>", callback_func_of_order_history)

        self.remove = ttk.Label(
            master=self.bottom_left_down_button_frame,
            image=self.image_buttons["clean"],
        )
        self.remove.pack(side=RIGHT)
        self.remove.bind("<Button-1>", self.remove_order_item_from_the_order_tree)
        # endregion

        # region 下层-订单树
        # order show container

        self.order_frame = ttk.Frame(
            master=self.bottom_frame,
            padding=2,
        )
        self.order_frame.pack(
            side=RIGHT,
            expand=True,
            fill=BOTH
        )
        self.order_frame.grid_rowconfigure(0, weight=1)
        self.order_frame.grid_columnconfigure(0, weight=1)

        column = ('货物编号', '货物名字', '货物价钱', '订购个数', '总价')
        self.order_tree = ttk.Treeview(
            master=self.order_frame,
            columns=column[1:],
            show=TREEHEADINGS,
            displaycolumns="#all",
            bootstyle="dark",
            height=5,
            selectmode=EXTENDED
        )
        self.xscroll = AutoScrollbar(
            master=self.order_frame,
            orient=HORIZONTAL,
            bootstyle="dark-round",
            command=self.order_tree.xview
        )
        self.yscroll = AutoScrollbar(
            master=self.order_frame,
            orient=VERTICAL,
            bootstyle="dark-round",
            command=self.order_tree.yview
        )
        self.order_tree.config(
            xscrollcommand=self.xscroll.set, yscrollcommand=self.yscroll.set)

        self.xscroll.grid(row=1, column=0, sticky=EW)
        self.yscroll.grid(row=0, column=1, sticky=NS)
        self.order_tree.grid(row=0, column=0, sticky=NSEW)

        self.order_tree.bind("<Double-Button-1>",
                             self.modify_order_from_order_tree)
        self.order_tree.heading("#0", text=column[0], anchor=W)
        self.order_tree.heading(column[1], text=column[1], anchor=W)
        self.order_tree.heading(column[2], text=column[2], anchor=W)
        self.order_tree.heading(column[3], text=column[3], anchor=W)
        self.order_tree.heading(column[4], text=column[4], anchor=W)
        self.order_tree.column(column="#0", anchor=W)
        self.order_tree.column(column=column[1], anchor=W)
        self.order_tree.column(column=column[2], anchor=W)
        self.order_tree.column(column=column[3], anchor=W)
        self.order_tree.column(column=column[4], anchor=W)
        # endregion
        # endregion

    def show_goods(self, *args):
        try:
            self.clean_goods_tree()
            item = 0
            all_groups = view.get_all_groups()
            if all_groups is False:
                return
            for group_id, group_name, group_image in all_groups:
                self.image_folder.append(ttk.ImageTk.PhotoImage(
                    image=view.set_image_size(
                        image_path=group_image,
                        size=view.GROUP_IMAGE_SIZE)
                ))
                father = self.goods_tree.insert(
                    parent="",
                    index=END,
                    text=group_name,
                    image=self.image_folder[item]
                )
                self.goods_tree.item(father, tags="group")
                item = item + 1
                goods = view.get_goods_from_group_name(group_name)
                if goods is False:
                    continue
                for good in goods:
                    self.image_folder.append(ttk.ImageTk.PhotoImage(
                        image=view.set_image_size(
                            image_path=good[4],
                            size=view.GOOD_IMAGE_SIZE
                        )
                    ))
                    self.goods_tree.insert(
                        parent=father,
                        index=END,
                        values=(good[0], good[2], good[3]),
                        image=self.image_folder[item]
                    )
                    item = item + 1
            self.goods_tree.tag_configure("group", font=(
                view.TREEVIEW_GROUP_FONT_FAMILY, view.TREEVIEW_GROUP_FONT_SIZE, view.TREEVIEW_GROUP_FONT_STYLE))
        except Exception as e:
            view.logger.error(traceback.print_exc())
            view.logger.error(e)

    def clean_goods_tree(self):
        self.image_folder.clear()
        x = self.goods_tree.get_children()
        for item in x:
            self.goods_tree.delete(item)

    def clean_orders_tree(self):
        self.image_folder.clear()
        x = self.order_tree.get_children()
        for item in x:
            self.order_tree.delete(item)

    def double_click_the_treeview_item_good(self, *args):
        try:
            is_group, item = self.decide_select_item_is_group_good(self.goods_tree)
            if is_group:
                showerror("错误", "您选的是货物组，请选择货物。")
            good_info_from_window = self.goods_tree.item(item, "values")
            good_info_from_db = view.get_goods_from_id(good_info_from_window[0])
            if not good_info_from_db:
                return
            callback_func_of_order_double_click_good(good_info_from_db)
        except Exception as e:
            view.logger.error(traceback.print_exc())
            view.logger.error(e)

    def decide_select_item_is_group_good(self, *args):
        groups = self.goods_tree.get_children()
        select_item = self.goods_tree.selection()
        if not select_item:
            showwarning("错误", "请选择一个元素")
            raise MyException("没选择元素")
        select_item = select_item[0]
        if select_item in groups:
            return True, select_item
        else:
            return False, select_item

    def print_order_tree(self):
        if not self.is_save_order.get():
            showerror("错误", "打印之前请保存订单。")
            return
        view.open_pdf(self.latest_order_group_id.get())

    def decide_select_item_order(self, *args):
        select_item = self.order_tree.selection()
        if not select_item:
            showwarning("错误", "请选择一个元素")
            raise MyException("没选择元素")
        return select_item[0]

    def modify_order_from_order_tree(self, *args):
        try:
            item = self.decide_select_item_order()
            # 获取选中的项的text 也就是good_id
            good_id = self.order_tree.item(item, "text")
            number = self.order_tree.item(item, "values")[2].replace('个', '')
            # 按照以上good_id的值,获取商品的全部信息
            good_info_from_db = list(view.get_goods_from_id(good_id))
            # 修改item信息需要提供iid
            good_info_from_db.append(item)
            # 调用修改信息窗口
            callback_func_of_modify_order(good_info_from_db, number)
        except Exception as e:
            showerror("错误", f"试图调出修改订单窗口失败。\n{e}")
            view.logger.error(traceback.print_exc())
            view.logger.error(e)

    def remove_order_item_from_the_order_tree(self, *args):
        """
        删除对应的元素
        :return:
        """
        try:
            item = self.decide_select_item_order()
            self.order_tree.delete(item)
            self.is_save_order.set(False)
        except Exception as e:
            view.logger.error(traceback.print_exc())
            view.logger.error(e)

    def save_order_tree(self):
        try:
            children = self.order_tree.get_children()
            if not children:
                showerror("错误", "请添加订单")
                return False
            # 所有order_tree中的订单，添加到all_goods数组中，以字典的方式，数据结构跟数据库中的类似
            all_goods = []
            for item in children:
                good_id = self.order_tree.item(item, 'text')
                values = self.order_tree.item(item, 'values')
                tmp = {
                    'good_id': good_id,
                    'good_name': values[0],
                    'price': values[1].replace("¥", ""),
                    'buy_number': values[2],
                    'sum_price': values[3]
                }
                all_goods.append(tmp)
            callback_func_of_save_order(all_goods)
        except Exception as e:
            view.logger.error(traceback.print_exc())
            view.logger.error(e)

    def track_the_is_save_order(self, *args):
        if self.is_save_order.get():
            self.save_order_btn['state'] = ttk.DISABLED
        else:
            self.save_order_btn['state'] = ttk.NORMAL


class OrderHistory(ttk.Toplevel):
    is_live = None

    def __init__(self, *args, **kwargs):
        super().__init__(minsize=(920, 590), title="历史订单", **kwargs)

        self.container = ttk.Frame(master=self)
        self.container.pack(fill=BOTH, expand=True)
        # self.styles = [
        #     ttk.Style().configure("joe.Treeview", rowheight=40, font=("JetBrains Mono", 15, "normal")),
        # ]
        self.new_styles = [
            ttk.Style().configure("joe.Treeview", rowheight=view.TREEVIEW_ROW_HEIGHT,
                                  font=("", 12, "")),
            # ttk.Style().configure("joe.TButton", font=("", 14, "")),
        ]

        # top container
        self.top_container = ttk.Frame(master=self.container, padding=4)
        self.top_container.pack(side=TOP, fill=X)

        # 提示
        ttk.Label(
            master=self.top_container,
            text="提示: 双击打开PDF文件",
            font=("", 12),
            foreground="blue"
        ).pack(side=LEFT, anchor=W)

        # buttons container
        self.button_container = ttk.Frame(master=self.top_container)
        self.button_container.pack(side=RIGHT, anchor=E)
        # 打开PDF
        ttk.Button(
            master=self.button_container,
            text="打卡",
            command=self.double_click_the_treeview_item,
            padding=5,
            bootstyle="success-outline"
        ).grid(row=0, column=0)
        self.button_container.grid_columnconfigure(index=1, minsize=40)
        # 移除单个
        ttk.Button(
            master=self.button_container,
            text="移除",
            command=self.remove_order,
            padding=5,
            bootstyle="danger-outline"
        ).grid(row=0, column=2)
        self.button_container.grid_columnconfigure(index=3, minsize=20)

        # 清空
        ttk.Button(
            master=self.button_container,
            text="清空历史记录",
            command=self.empty_order,
            padding=5,
            bootstyle="danger-outline"
        ).grid(row=0, column=4)

        # 渲染订单
        self.frame_of_orders = ttk.Frame(
            master=self.container,
            padding=2,
            borderwidth=2,
        )
        self.frame_of_orders.pack(side=BOTTOM, fill=BOTH, expand=True)

        self.frame_of_orders.grid_rowconfigure(index=0, weight=1)
        self.frame_of_orders.grid_columnconfigure(index=0, weight=1)

        self.orders_tree = ttk.Treeview(
            master=self.frame_of_orders,
            columns=(0, 1, 2),
            show=TREEHEADINGS,
            displaycolumns="#all",
            bootstyle="primary"
        )
        self.xscroll = AutoScrollbar(
            master=self.frame_of_orders,
            orient=HORIZONTAL,
            bootstyle="primary-round",
            command=self.orders_tree.xview
        )
        self.yscroll = AutoScrollbar(
            master=self.frame_of_orders,
            orient=VERTICAL,
            bootstyle="primary-round",
            command=self.orders_tree.yview
        )
        self.orders_tree.configure(
            xscrollcommand=self.xscroll.set, yscrollcommand=self.yscroll.set)

        self.xscroll.grid(row=1, column=0, sticky=EW)
        self.yscroll.grid(row=0, column=1, sticky=NS)
        self.orders_tree.grid(row=0, column=0, sticky=NSEW)

        self.orders_tree.bind("<Double-Button-1>",
                              self.double_click_the_treeview_item)
        self.orders_tree.heading("#0", text='订单编号', anchor=CENTER)
        self.orders_tree.heading(0, text='备注', anchor=CENTER)
        self.orders_tree.heading(1, text='创建时间', anchor=CENTER)
        self.orders_tree.heading(2, text='PDF文件存放位置', anchor=CENTER)
        # self.orders_tree.heading(2, text='image', anchor=CENTER)
        self.orders_tree.column(
            column="#0",
            width=utility.scale_size(self, 20),
            anchor=CENTER
        )
        self.orders_tree.column(
            column=0,
            width=utility.scale_size(self, 50),
            anchor=CENTER
        )
        self.orders_tree.column(
            column=1,
            width=utility.scale_size(self, 300),
            anchor=CENTER
        )
        self.orders_tree.column(
            column=2,
            width=utility.scale_size(self, 300),
            anchor=CENTER
        )
        # self.image_folder = ttk.PhotoImage(
        #     file="/Users/joe/Documents/DaYinJi/Order-System/assets/folder.png").subsample(30, 30)
        self.show_history()

    def show_history(self, *args):
        try:
            self.clean_orders_tree()
            all_order_group = view.get_all_order_group()
            if all_order_group is False:
                return
            for order_group_id, create_date, order_path, remark in all_order_group:
                self.orders_tree.insert(
                    parent="",
                    index=END,
                    text=order_group_id,
                    values=(remark, create_date, order_path)
                )
        except Exception as e:
            view.logger.error(traceback.print_exc())
            view.logger.error(e)
            showerror("系统错误", f"获取历史订单时出错。\n{e}")

    def clean_orders_tree(self):
        x = self.orders_tree.get_children()
        for item in x:
            self.orders_tree.delete(item)

    def select_item(self):
        item = self.orders_tree.selection()
        if not item:
            showerror("错误", "请选择一个订单。")
            raise MyException("没选择元素")
        return item[0]

    def double_click_the_treeview_item(self, *args):
        try:
            item = self.select_item()
            order_info_from_window = self.orders_tree.item(item, "text")
            view.open_pdf(order_info_from_window)
        except Exception as e:
            view.logger.error(traceback.print_exc())
            view.logger.error(e)

    def remove_order(self):
        """
        1.查找选择的元素
        2.删除查找的订单信息，pdf文件
        3.冲order_tree中删除对应的记录
        """
        try:
            item = self.select_item()
            order_group_id = self.orders_tree.item(item, "text")
            # 先删除PDF文件
            if not view.remove_single_pdf(order_group_id):
                # pdf删除失败，会询问用户是否继续删除
                if not askyesno("继续删除", "是否强制删除数据库中的订单信息？"):
                    # 不想删除，什么都不做
                    return
            # pdf删除成功/用户强制删除都会执行数据库中删除订单信息操作
            if not view.delete_order_group_by_order_group_id(order_group_id):
                return
            # 移除order_tree中指定的item
            self.orders_tree.delete(item)
        except Exception as e:
            view.logger.error(traceback.print_exc())
            view.logger.error(e)

    def empty_order(self):
        if not askyesno("确认", "清空所有记录将无法找回，会永久性删除，确定要清空吗？"):
            return
        all_order_group = view.get_all_order_group()
        if all_order_group is False:
            return
        # 删除PDF文件
        for order_group_id, create_date, order_path, remark in all_order_group:
            view.remove_multiple_pdf(order_path)
        # 删除所有订单记录
        if not view.delete_all_order():
            return
        self.clean_orders_tree()


if __name__ == '__main__':
    view.ROOT_WINDOW = ttk.Window(
        title="货物管理",
        themename=view.THEME,
        iconphoto=None,
        minsize=(830, 400),
        maxsize=(830, 440),
        scaling=1,
    )
    # view.ORDER = Order(view.ROOT_WINDOW)
    # order_tmp = Order()
    # order_tmp.order_tree.insert(
    #     "", END, text='1', values=('椅子', '3.00', '12个', '36¥')
    # )
    view.INDEX = Index(view.ROOT_WINDOW)
    view.ROOT_WINDOW.mainloop()
